﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Rhino.Mocks;

using CloudStorage.API.Messages;
using CloudStorage.API.Messages.Extensions;

namespace CloudStorage.Tests.API.Messages.Extensions
{
	[TestClass]
	public class MessageDataContextExtensionsTests
	{
		[TestMethod]
		public void GetMessage_gets_one_message()
		{
			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			var message = MockRepository.GenerateStub<IMessage>();
			IEnumerable<IMessage> messages = new List<IMessage> { message };

			messageDataContext.Expect(m => m.GetMessages(1))
												.Return(messages);

			// Act
			IMessage result = messageDataContext.GetMessage();

			Assert.AreSame(message, result);

			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod]
		public void GetMessage_with_visibilityTimeoutInSeconds()
		{
			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			var message = MockRepository.GenerateStub<IMessage>();
			IEnumerable<IMessage> messages = new List<IMessage> { message };

			var visibilityTimeoutInSeconds = 42;
			messageDataContext.Expect(m => m.GetMessages(1, visibilityTimeoutInSeconds))
												.Return(messages);

			// Act
			IMessage result = messageDataContext.GetMessage(visibilityTimeoutInSeconds);

			Assert.AreSame(message, result);

			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod]
		public void PeekMessage_gets_one_messageInfo()
		{
			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			var messageInfo = MockRepository.GenerateStub<IMessageInfo>();
			IEnumerable<IMessageInfo> messages = new List<IMessageInfo> { messageInfo };

			messageDataContext.Expect(m => m.PeekMessages(1)).Return(messages);

			// Act
			IMessageInfo result = messageDataContext.PeekMessage();

			Assert.AreSame(messageInfo, result);

			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod]
		public void HasMessage_no_message_returns_false()
		{
			IEnumerable<IMessageInfo> expectedMessages = Enumerable.Empty<IMessageInfo>();

			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			messageDataContext.Expect(mdc => mdc.PeekMessages(1))
												.Return(expectedMessages);

			// Act
			var result = messageDataContext.HasMessage();

			Assert.IsFalse(result);
			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod]
		public void HasMessage_message_exists_returns_true()
		{
			var expectedMessage = MockRepository.GenerateStub<IMessage>();
			IEnumerable<IMessageInfo> expectedMessages = new[] { expectedMessage };

			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			messageDataContext.Expect(mdc => mdc.PeekMessages(1))
												.Return(expectedMessages);

			// Act
			var result = messageDataContext.HasMessage();

			Assert.IsTrue(result);
			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod]
		public void DeleteMessage_OK()
		{
			var messageId = "foo";
			var popReciept = "bar";
			var expectedMessage = MockRepository.GenerateStub<IMessage>();
			expectedMessage.Expect(m => m.Id)
										 .Return(messageId);
			expectedMessage.Expect(m => m.PopReceipt)
										 .Return(popReciept);

			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();
			messageDataContext.Expect(mdc => mdc.DeleteMessage(messageId, popReciept));

			// Act
			messageDataContext.DeleteMessage(expectedMessage);

			messageDataContext.VerifyAllExpectations();
		}

		[TestMethod, ExpectedException(typeof(ArgumentNullException))]
		public void DeleteMessage_missing_message_Fails()
		{
			var messageDataContext = MockRepository.GenerateMock<IMessageDataContext>();

			// Act
			messageDataContext.DeleteMessage(null);
		}
	}
}